import * as vscode from "vscode";
import { nowLog } from "../data";
export class OutputChannel {
  static name: string = "OutputChannel";
  public static setOutputChannel(name: string) {
    this.name = name;
    return this;
  }
  static instance: OutputChannel;
  static getInstance() {
    if (!OutputChannel.instance) {
      OutputChannel.instance = new OutputChannel();
    }
    return OutputChannel.instance;
  }

  private outputChannel: vscode.LogOutputChannel;
  private constructor() {
    this.outputChannel = vscode.window.createOutputChannel(OutputChannel.name, {
      log: true,
    });
  }
  public appendLine(value: string) {
    this.outputChannel.appendLine(value);
    return this;
  }
  public info(value: string) {
    this.outputChannel.info(value);
    return this;
  }
  public warn(value: string) {
    this.outputChannel.warn(value);
    return this;
  }
  public error(value: string) {
    this.outputChannel.error(value);
    return this;
  }
  public debug(value: string) {
    this.outputChannel.appendLine(value);
    return this;
  }
  public trace(value: string) {
    this.outputChannel.appendLine(value);
    return this;
  }
  public verbose(value: string) {
    return this.trace(value);
  }
  public show() {
    this.outputChannel.show();
    return this;
  }
  public getOutputChannel() {
    return this.outputChannel;
  }
  public clear() {
    this.outputChannel.clear();
  }
  public dispose() {
    this.outputChannel.dispose();
  }
}

export class OutputWrapper {
  static OutputType = {
    INFO: "info",
    WARN: "WARN",
    ERROR: "error",
    SUCCESS: "SUCCESS",
    LOG: "LOG",
  };
  constructor(
    private outputChannel: OutputChannel,
    protected prefix?: string,
  ) {}
  private generate(
    msg: string,
    type: (typeof OutputWrapper.OutputType)[keyof typeof OutputWrapper.OutputType],
  ) {
    const prefix = `${this.prefix ? "(" + this.prefix + ")" : ""}`;
    return msg
      ?.toString()
      .replace(/\x1b\[[0-9;]*m/g, "")
      ?.split("\n")
      .map((line) => `${prefix} ${line}`)
      .join("\n");
  }
  public info(msg: string) {
    if (msg.includes("ERROR")) {
      OutputChannel.getInstance().show();
    }
    this.outputChannel.info(this.generate(msg, OutputWrapper.OutputType.INFO));
    return this;
  }
  public warn(msg: string) {
    this.outputChannel.warn(this.generate(msg, OutputWrapper.OutputType.WARN));
  }
  public error(msg: string) {
    this.outputChannel.error(
      this.generate(msg, OutputWrapper.OutputType.ERROR),
    );
    OutputChannel.getInstance().show();
  }
  public success(msg: string) {
    this.outputChannel.info(
      this.generate(msg, OutputWrapper.OutputType.SUCCESS),
    );
  }
  public log(msg: string) {
    this.outputChannel.info(this.generate(msg, OutputWrapper.OutputType.LOG));
  }
  public debug(msg: string) {
    this.outputChannel.debug(this.generate(msg, OutputWrapper.OutputType.INFO));
    OutputChannel.getInstance().show();
  }
  public trace(msg: string) {
    this.outputChannel.trace(this.generate(msg, OutputWrapper.OutputType.INFO));
  }
  public verbose(msg: string) {
    this.outputChannel.verbose(
      this.generate(msg, OutputWrapper.OutputType.INFO),
    );
  }
}
